home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The 640 MEG Shareware Studio 2
/
The 640 Meg Shareware Studio CD-ROM Volume II (Data Express)(1993).ISO
/
pascal
/
ems_tp.zip
/
EMS_DEMO.PAS
Wrap
Pascal/Delphi Source File
|
1989-08-15
|
9KB
|
222 lines
{$R-} {Range checking off}
{$B+} {Boolean complete evaluation on}
{$S+} {Stack checking on}
{$I+} {I/O checking on}
{$N-} {No numeric coprocessor}
{$M 65500,16384,655360} {Turbo 3 default stack and heap}
{ $p256}
{!^ 1. Directives A,B,C,D,F,G,P,U,W,X are obsolete or changed in meaning}
Program ems_demo;
{ This program is a demo of the use of EMS procedures in Turbo Pascal. }
{ Public Domain by Peter Handsman. GEnie Mail: P.Handsman }
{ Any problems or damage this program does is NOT my fault! }
{ I therefore take no responsibility whatsoever. }
{ Keeping that in mind I welcome and comments or questions or bug reports}
{ }
{ The program start's out by checking if you have EMS installed... }
{ Moves on to a short demo of allocating memory and what happens to }
{ free EMS memory. Then Runs the Sieve of Erat(who knows?) with the }
{ data array in an allocated part of EMS memory. }
{ }
{ EMS memory is the specification by Lotus/Intel/Microsoft for a banked }
{ memory scheme. The PD file Limspec.arc defines the spec. }
{ This program was written on a IBM PC with a AST Rampage! board }
{ (But it does not use the extended spec's) and the source is in }
{ Turbo Pascal 3.01a. }
Uses
Dos; {Unit found in TURBO.TPL}
const
SIZE = 8190; { Used by the prime sieve.}
type
registers= record { 8088 regester type. }
ax,bx,cx,dx,bp,si,di,ds,es,flags:integer;
{! 2. Instead use the Registers type from the^ Turbo 5.0 DOS unit.}
end;
handle_rec=record { Handle map record type. }
handle: integer;
numpages:integer;
end;
pages= array[0..255] of handle_rec;
pages_ptr= ^pages;
arr = record { the following types are }
flag: array[0..8191] of byte; { used by the prime sieve. }
end;
parr = ^arr;
var
han: integer; { Holds the handle returned by alloc}
regs: registers; { Holds the 8088 regester set. }
handles: integer; { Holds number of used handles. }
map: pages_ptr; { Ptr to ems page map. }
segm: integer; { Holds segment of ems window. }
f: parr; { Ptr to prime data array. }
j,k,count: integer; { Misc var's for prime sieve. }
prime: integer; { Holds prime number. }
procedure error_handler(error_num:integer);
{ This is a lame error handler... all it does is print out a }
{ message and halt, setting ERRORLEVEL to the error number. }
{ Since some errors are not fatel, i.e. not enough free pages }
{ You should include more code here to trap specific errors. }
{ A listing of what the error numbers mean is in the }
{ Limspec.arc public domain file... }
begin
writeln('EMS Error number: ',error_num,' has occured...');
halt(error_num)
end;
function cnvt_bcd_bytes(i:integer):real;
{ This function takes a bcd number then converts it to bytes. }
{ The bcd number is of the format xxxxyyyy in binary where }
{ the number is the number of pages (16k to a page) }
begin
cnvt_bcd_bytes:=(256.0*hi(i)+lo(i))*1024.0*16.0;
end;
function ems_installed:boolean;
{ This function checks to see if a ems board is installed... }
{ If you have a ems board and haven't installed the device }
{ which controls it, (the EMM manager) then it will respond }
{ as if you don't have such a board. }
var
f:file;
begin
assign(f, 'EMMXXXX0');
{$I-} reset(f) {$I+} ;
ems_installed:=(ioresult=0)
{! 3. IOResult now re^turns different values corresponding to DOS error codes.}
end;
procedure emm_call(var regs:registers; ah:integer);
{ This procedure makes a call to the emm device and executes }
{ the function specified in the ah parameter... also it calls }
{ the error_handler if the emm manager returns an error msg. }
begin
regs.ax:=ah*$100;
intr($67,Dos.Registers(regs));
{! 4. Paramete^r to Intr must be of the type Registers defined in DOS unit.}
if hi(regs.ax)<>0 then error_handler(hi(regs.ax));
end;
procedure print_map(var page_map:pages; handles:integer);
{ This procedure obtains the page_map from the EMM device and }
{ prints it out in a readable form. }
var
h:integer;
begin
regs.es:=seg(page_map); { call with the address where }
regs.di:=ofs(page_map); { you want the map to be placed.}
regs.bx:=0;
emm_call(regs,$4d);
writeln;
writeln('Handle bytes');
writeln('------ ------');
for h:=0 to handles-1 do
writeln(h:5, ' ',cnvt_bcd_bytes(page_map[h].numpages):8:0)
end;
procedure show_info;
{ This procedure prints out some information on the current }
{ state of the ems memory and the memory handler. }
begin
emm_call(regs,$4b); { Get the total number of handles }
handles:=regs.bx; { in use. }
getmem(map,4*handles);
print_map(map^,handles);{ Get the free and total space. }
emm_call(regs,$42);
writeln(' free: ',cnvt_bcd_bytes(regs.bx):8:0);
writeln('total: ',cnvt_bcd_bytes(regs.dx):8:0);
emm_call(regs,$46);
writeln('The EMM version is: ',lo(regs.ax)/16:2:0,'.',lo(regs.ax) mod 16:1)
end;
procedure alloc(num:integer;var handle:integer);
{ This procedure allocates num pages(16k) of ems memory which }
{ can be refered to by the map handle. }
{ WARNING: if you allocate memory and don't deallocate it the }
{ memory will be lost till power off. }
begin
regs.bx:=num;
emm_call(regs,$43);
handle:=regs.dx
end;
procedure unalloc(handle:integer);
{ This procedure unallocates ems memory. You MUST have the }
{ handle number or you can't unallocate anything! }
begin
regs.dx:=handle;
emm_call(regs,$45);
end;
procedure get_page_frame(var address:integer);
{ This procedure gets the segment address of the start of where}
{ the ems memory will be maped onto the normal 8088 memory }
{ address space... }
begin
emm_call(regs,$41);
address:=regs.bx
end;
procedure set_page(logical_page,physical_page,handle:integer);
{ This procedure sets the logical page onto one of the four }
{ physical pages which the normal lim spec's provide for. }
{ }
{ Logical_Page is from 0 to the number of pages allocated }
{ for that handle-1. }
{ Physical_Page is one of the four(0-3) pages. This will over- }
{ write any previous calls so use differnt ones }
{ until you don't need the old logical page for }
{ a while. }
{ }
{ Offsets from the page_frame segment are: }
{ page:offset 0:0000 1:4000 2:8000 3:C0000 in hex. }
begin
regs.ax:=($44*$100)+physical_page;
regs.bx:=logical_page;
regs.dx:=handle;
intr($67,Dos.Registers(regs));
if hi(regs.ax)<>0 then error_handler(hi(regs.ax))
end;
procedure sieve(f:parr);
{ This is a sieve demo... using a array in EMS memory. }
begin
writeln(' interations: 1 ') ;
count:=0;
for j:=0 to SIZE do f^.flag[j]:=1;
for j:=0 to SIZE do
if f^.flag[j]=1 then begin
prime:= j + j + 3 ;
write(prime,' '); { Comment out this line to drop prime printing}
k:=j+prime;
while (k<=size) do begin
f^.flag[k]:=0;
k:=k+prime
end;
count:=count+1
end;
writeln('Primes found.=', count )
end;
begin
if ems_installed then begin { Otherwise just print out msg.}
show_info; { Trivial show of just what }
alloc(2,han); { happens to free ems memory...}
show_info; { . }
unalloc(han); { . }
show_info; { . }
alloc(1,han);
get_page_frame(segm); { Setup for ems memory usage. }
set_page(0,0,han); { Set logical page to physical.}
f:=ptr(segm,$0000); { Set ptr to absolute address. }
sieve(f); { For above see p207 in tpas manual}
unalloc(han);
end else writeln('No EMS manager installed.')
end.